import axios from 'axios';
import { ElMessage } from 'element-plus';

/**
 * 创建axios实例
 */
const service = axios.create({
  // baseURL: process.env.VUE_APP_BASE_API || '/api', // 基础API地址
  baseURL: import.meta.env.VITE_APP_BASE_API || '',
  timeout: 10000, // 请求超时时间
});

// 全局状态控制
let isRefreshing = false;
let refreshQueue = [];
let _router = null;

/**
 * Token刷新函数
 * @returns 
 */
const refreshToken = async () => {
  if (isRefreshing) return;

  try {
    isRefreshing = true;
    const { data } = await axios.post('/auth/refresh', {
      refresh_token: localStorage.getItem('refresh_token')
    }, { headers: { 'Content-Type': 'application/json' } });

    // 更新双Token
    localStorage.setItem('token', data.token);
    localStorage.setItem('refresh_token', data.refresh_token);

    // 处理排队请求
    refreshQueue.forEach(cb => cb(data.token));
    refreshQueue = [];

    return data.token;
  } catch (error) {
    console.error('Token刷新失败:', error);
    localStorage.removeItem('token');
    localStorage.removeItem('refresh_token');
    _router.push('/login');
  } finally {
    isRefreshing = false;
  }
};

/**
 * 请求拦截器
 */
service.interceptors.request.use(
  config => {
    /**
     * 在发送请求之前做些什么
     */
    const token = localStorage.getItem('token') || sessionStorage.getItem('token');
    if (token) {
      config.headers['Authorization'] = `Bearer ${token}`;
    }

    /**
     * 添加时间戳防止缓存（仅对GET请求）
     */
    if (config.method === 'get') {
      config.params = {
        ...config.params,
        _t: Date.now()
      };
    }

    /**
     * 如果是上传文件，设置Content-Type
     */
    if (config.isUpload) {
      config.headers['Content-Type'] = 'multipart/form-data';
    }

    // console.log(`发起请求: ${config.method?.toUpperCase()} ${config.url}`);
    return config;
  },
  error => {
    // 请求错误
    console.error('请求错误:', error);
    return Promise.reject(error);
  }
);

/**
 * 响应拦截器
 */
service.interceptors.response.use(
  response => {
    /**
     * 对响应数据做点什么
     */
    const res = response.data;

    const newToken = response.headers['x-refresh-token'];
    if (newToken) {
      localStorage.setItem('token', newToken);
      // 更新axios默认Authorization头
      axios.defaults.headers.common['Authorization'] = `Bearer ${newToken}`;
    }

    /**
     * 根据后端返回的状态码进行判断
     */
    if (res.code === 200) {
      return res;
    } else if (res.code === 401) {
      /**
       * 未授权，跳转到登录页
       */
      ElMessage.error('登录已过期，请重新登录');
      localStorage.removeItem('user');
      localStorage.removeItem('enums');
      localStorage.removeItem('token');
      sessionStorage.removeItem('token');
      _router.push('/login');
      return Promise.reject(new Error(res.message || 'Error'));
    } else if (res.code === 403) {
      /**
       * 无权限访问
       */
      ElMessage.error('没有权限访问该资源');
      return Promise.reject(new Error(res.message || 'Error'));
    } else if (res.code === 409) {
      /**
       * 请求冲突
       */
      ElMessage.error('资源请求冲突');
      return Promise.reject(new Error(res.message || 'Error'));
    } else if (res.code === 500) {
      /**
       * 服务器错误
       */
      ElMessage.error(res.message || '服务器内部错误');
      return Promise.reject(new Error(res.message || 'Error'));
    } else {
      /**
       * 其他错误
       */
      ElMessage.error(res.message || '请求失败');
      return Promise.reject(new Error(res.message || 'Error'));
    }
  },
  error => {
    /**
     * 响应错误
     */
    let msg = '请求错误';

    if (error.response) {
      switch (error.response.status) {
        case 400:
          msg = error.response.data.message || '请求参数错误';
          break;
        case 401:
          msg = '未授权，请重新登录';
          localStorage.removeItem('token');
          sessionStorage.removeItem('token');
          _router.push('/login'); // config noLogout
          break;
        case 403:
          msg = '拒绝访问';
          break;
        case 404:
          msg = `请求地址出错: ${error.response.config.url}`;
          break;
        case 408:
          msg = '请求超时';
          break;
        case 409:
          msg = error.response.data.message || '请求超时';
          break;
        case 500:
          msg = '服务器内部错误';
          break;
        case 501:
          msg = '服务未实现';
          break;
        case 502:
          msg = '网关错误';
          break;
        case 503:
          msg = '服务不可用';
          break;
        case 504:
          msg = '网关超时';
          break;
        case 505:
          msg = 'HTTP版本不受支持';
          break;
        default:
          msg = `连接错误${error.response.status}`;
      }
    } else if (error.message.includes('timeout')) {
      msg = '网络请求超时';
    } else if (error.message === 'Network Error') {
      msg = '网络错误，请检查网络连接';
    }

    ElMessage.error(msg);
    console.warn('响应错误:', error);
    return Promise.reject(error);
  }
);

/**
 * 请求方法封装
 */
const request = {
  /**
   * GET请求
   * @param {string} url 请求地址
   * @param {object} params 请求参数
   * @param {object} config 请求配置
   */
  get(url, params = {}, config = {}) {
    return service.get(url, { params, ...config });
  },

  /**
   * POST请求
   * @param {string} url 请求地址
   * @param {object} data 请求数据
   * @param {object} config 请求配置
   */
  post(url, data = {}, config = {}) {
    return service.post(url, data, config);
  },

  /**
   * PUT请求
   * @param {string} url 请求地址
   * @param {object} data 请求数据
   * @param {object} config 请求配置
   */
  put(url, data = {}, config = {}) {
    return service.put(url, data, config);
  },

  /**
   * DELETE请求
   * @param {string} url 请求地址
   * @param {object} config 请求配置
   */
  delete(url, config = {}) {
    return service.delete(url, config);
  },

  /**
   * 上传文件
   * @param {string} url 请求地址
   * @param {FormData} formData 表单数据
   * @param {object} config 请求配置
   */
  upload(url, formData, config = {}) {
    return service.post(url, formData, {
      ...config,
      isUpload: true, // 自定义标记，用于拦截器识别
      headers: {
        'Content-Type': 'multipart/form-data',
        ...config.headers
      }
    });
  },

  /**
   * 下载文件
   * @param {string} url 请求地址
   * @param {object} params 请求参数
   * @param {string} filename 下载文件名
   * @param {object} config 请求配置
   */
  download(url, params = {}, filename = 'file', config = {}) {
    return service.get(url, {
      params,
      responseType: 'blob',
      ...config
    }).then(response => {
      // 创建blob对象
      const blob = new Blob([response.data]);

      // 创建下载链接
      const downloadUrl = window.URL.createObjectURL(blob);
      const link = document.createElement('a');
      link.href = downloadUrl;
      link.download = filename;
      document.body.appendChild(link);
      link.click();

      // 清理
      document.body.removeChild(link);
      window.URL.revokeObjectURL(downloadUrl);
    });
  }
};

export function initRequest(router) {
  _router = router;
  return request;
}